/*
 * 描述： <描述>
 * 修改人： rain
 * 修改时间： 2016年01月20日
 * 项目： rainhy-cores-core
 */
package com.rainhy.core.util;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.helpers.MessageFormatter;

import com.rainhy.core.exception.RainhyIllegalArgException;
import com.rainhy.core.util.PatternUtils.RegExp;

/**
 * 断言工具<br>
 * > gt 大于<br>
 * < lt 小于<br>
 * >= ge 大于等于<br>
 * <= le 小于等于<br>
 * 
 * @author rain
 * @version [版本号, 2015年12月14日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public abstract class AssertUtils {
    
    /**
     * 
     * 断言在两个值之间(包括)
     *
     * @param value 值
     * @param minInclusive 最小值(包括)
     * @param maxInclusive 最大值(包括)
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static void between(BigDecimal value, BigDecimal minInclusive, BigDecimal maxInclusive, String message, Object... parameters) {
        notNullByAll(new BigDecimal[] { value, minInclusive, maxInclusive }, message, parameters);
        isTrue((minInclusive.compareTo(value) <= 0) && (value.compareTo(maxInclusive) <= 0), message, parameters);
    }
    
    /**
     * 
     * 断言在两个值之间(包括)
     *
     * @param value 值
     * @param minInclusive 最小值(包括)
     * @param maxInclusive 最大值(包括)
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static void between(double value, double minInclusive, double maxInclusive, String message, Object... parameters) {
        isTrue((minInclusive <= value) && (value <= maxInclusive), message, parameters);
    }
    
    /**
     * 
     * 断言在两个值之间(包括)
     *
     * @param value 值
     * @param minInclusive 最小值(包括)
     * @param maxInclusive 最大值(包括)
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static void between(float value, float minInclusive, float maxInclusive, String message, Object... parameters) {
        isTrue((minInclusive <= value) && (value <= maxInclusive), message, parameters);
    }
    
    /**
     * 
     * 断言在两个值之间(包括)
     *
     * @param value 值
     * @param minInclusive 最小值(包括)
     * @param maxInclusive 最大值(包括)
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static void between(int value, int minInclusive, int maxInclusive, String message, Object... parameters) {
        isTrue((minInclusive <= value) && (value <= maxInclusive), message, parameters);
    }
    
    /**
     * 
     * 断言在两个值之间(包括)
     *
     * @param value 值
     * @param minInclusive 最小值(包括)
     * @param maxInclusive 最大值(包括)
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static void between(long value, long minInclusive, long maxInclusive, String message, Object... parameters) {
        isTrue((minInclusive <= value) && (value <= maxInclusive), message, parameters);
    }
    
    /**
     * 
     * 断言 字符串 cs 包含 searchChars
     *
     * @param cs 被断言的字符串
     * @param searchChars 包含的值
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月5日]
     * @author rain
     */
    public static void contains(CharSequence cs, char searchChars, String message, Object... parameters) {
        AssertUtils.isTrue(StringUtils.containsAny(cs, searchChars), message, parameters);
    }
    
    /**
     * 
     * 断言 字符串 cs 包含 searchChars
     *
     * @param cs 被断言的字符串
     * @param searchChars 包含的值
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月5日]
     * @author rain
     */
    public static void contains(CharSequence cs, CharSequence searchChars, String message, Object... parameters) {
        AssertUtils.isTrue(StringUtils.containsAny(cs, searchChars), message, parameters);
    }
    
    /**
     * 
     * 断言 value 存在
     *
     * @param coll 断言对象
     * @param value 断言 value
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月10日]
     * @author rain
     */
    public static <V> void contains(Collection<V> coll, V value, String message, Object... parameters) {
        AssertUtils.isTrue(coll.contains(value), message, parameters);
    }
    
    /**
     * 
     * 断言 key 对应的值存在
     *
     * @param map 断言对象
     * @param key 断言 key
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月10日]
     * @author rain
     */
    public static <K> void contains(Map<K, ?> map, K key, String message, Object... parameters) {
        AssertUtils.isTrue(map.containsKey(key), message, parameters);
    }
    
    /**
     * 
     * 断言 coll1 和 coll2 有相同元素
     *
     * @param coll1 集合1
     * @param coll2 集合2
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see org.apache.commons.collections.CollectionUtils#containsAny(Collection, Collection)
     * @version [版本号, 2016年8月25日]
     * @author rain
     */
    public static <K> void containsAny(Collection<K> coll1, Collection<K> coll2, String message, Object... parameters) {
        AssertUtils.isTrue(CollectionUtils.containsAny(coll1, coll2), message, parameters);
    }
    
    /**
     * 
     * 断言两个对象相等<br>
     * 通过 "=="和"equals"一起 判断<br>
     *
     * @param object1 对象1
     * @param object2 对象2
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月16日]
     * @author rain
     */
    public static void equals(Object object1, Object object2, String message, Object... parameters) {
        if (!Objects.equals(object1, object2)) {
            fail(message);
        }
    }
    
    /**
     * 
     * 抛出异常
     *
     * @param message 异常信息
     * @param parameters 提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void fail(String message, Object... parameters) {
        throw new RainhyIllegalArgException(MessageFormatter.arrayFormat(message, parameters).getMessage());
    }
    
    /**
     * 
     * 断言字符串为空<br>
     * 提示信息样例: "{} is null!"."{}"就是参数,可以无限个
     *
     * @param cs 断言字符
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月22日]
     * @author rain
     */
    public static void isBlank(CharSequence cs, String message, Object... parameters) {
        if (StringUtils.isNotBlank(cs)) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言对象为 空<br>
     *
     * @param object 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void isEmpty(Object object, String message, Object... parameters) {
        if (!CheckUtils.isEmpty(object)) {
            fail(message, parameters);
        }
    }
    
    /**
     * 断言对象为 false
     *
     * @param bool 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void isFalse(boolean bool, String message, Object... parameters) {
        if (bool) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言对象为空
     *
     * @param object 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年2月22日]
     * @author rain
     */
    public static void isNull(Object object, String message, Object... parameters) {
        if (object != null) {
            fail(message, parameters);
        }
    }
    
    /**
     * 断言对象为 true
     *
     * @param bool 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void isTrue(boolean bool, String message, Object... parameters) {
        if (!bool) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言 字符串 cs 匹配正则表达式: regexp
     *
     * @param cs 被断言的字符串
     * @param regexp 正则表达式
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月11日]
     * @author rain
     */
    public static void matcher(CharSequence cs, RegExp regexp, String message, Object... parameters) {
        AssertUtils.isTrue(PatternUtils.matcher(regexp, cs.toString()), message, parameters);
    }
    
    /**
     * 
     * 断言 字符串 cs 匹配正则表达式: regexp
     *
     * @param cs 被断言的字符串
     * @param regexp 正则表达式
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月11日]
     * @author rain
     */
    public static void matcher(CharSequence cs, String regexp, String message, Object... parameters) {
        AssertUtils.isTrue(PatternUtils.matcher(regexp, cs.toString()), message, parameters);
    }
    
    /**
     * 
     * 断言字符串不为空<br>
     * 提示信息样例: "{} is null!"."{}"就是参数,可以无限个
     *
     * @param cs 断言字符
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月22日]
     * @author rain
     */
    public static void notBlank(CharSequence cs, String message, Object... parameters) {
        if (StringUtils.isBlank(cs)) {
            fail(message, parameters);
        }
    }
    
    /**
     * 断言字符串集合里面有一个字符串不为空
     *
     * @param strings 字符串
     * @param message 异常信息
     * @param parameters 提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年2月21日]
     * @author rain
     */
    public static void notBlankByOne(Collection<String> strings, String message, Object... parameters) {
        if (CollectionUtils.isEmpty(strings)) {
            fail(message, parameters);
        }
        
        boolean allEmpty = true;
        for (String str : strings) {
            if (StringUtils.isNotBlank(str)) {
                allEmpty = false;
            }
        }
        if (allEmpty) {
            fail(message, parameters);
        }
    }
    
    /**
     * 断言字符串数组里面有一个字符串不为空
     *
     * @param strings 字符串
     * @param message 异常信息
     * @param parameters 提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月16日]
     * @author rain
     */
    public static void notBlankByOne(String[] strings, String message, Object... parameters) {
        if (ArrayUtils.isEmpty(strings)) {
            fail(message, parameters);
        }
        
        boolean allEmpty = true;
        for (String str : strings) {
            if (StringUtils.isNotBlank(str)) {
                allEmpty = false;
            }
        }
        if (allEmpty) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言 字符串 cs 不包含 searchChars
     *
     * @param cs 被断言的字符串
     * @param searchChars 包含的值
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月5日]
     * @author rain
     */
    public static void notContains(CharSequence cs, char searchChars, String message, Object... parameters) {
        AssertUtils.isFalse(StringUtils.containsAny(cs, searchChars), message, parameters);
        
    }
    
    /**
     * 
     * 断言 字符串 cs 不包含 searchChars
     *
     * @param cs 被断言的字符串
     * @param searchChars 包含的值
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月5日]
     * @author rain
     */
    public static void notContains(CharSequence cs, CharSequence searchChars, String message, Object... parameters) {
        AssertUtils.isFalse(StringUtils.containsAny(cs, searchChars), message, parameters);
    }
    
    /**
     * 
     * 断言 value 不存在
     *
     * @param coll 断言对象
     * @param value 断言 value
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月10日]
     * @author rain
     */
    public static <K> void notContains(Collection<K> coll, K key, String message, Object... parameters) {
        AssertUtils.isFalse(coll.contains(key), message, parameters);
    }
    
    /**
     * 
     * 断言 key 对应的值不存在
     *
     * @param map 断言对象
     * @param key 断言 key
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月10日]
     * @author rain
     */
    public static <K> void notContains(Map<K, ?> map, K key, String message, Object... parameters) {
        AssertUtils.isFalse(map.containsKey(key), message, parameters);
    }
    
    /**
     * 
     * 断言 coll1 和 coll2 没有相同元素
     *
     * @param coll1 集合1
     * @param coll2 集合2
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月25日]
     * @author rain
     */
    public static <K> void notContainsAny(Collection<K> coll1, Collection<K> coll2, String message, Object... parameters) {
        AssertUtils.isFalse(CollectionUtils.containsAny(coll1, coll2), message, parameters);
    }
    
    /**
     * 
     * 断言对象不为空<br>
     * 提示信息样例: "{} is null!"."{}"就是参数,可以无限个
     *
     * @param object 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void notEmpty(Object object, String message, Object... parameters) {
        if (CheckUtils.isEmpty(object)) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言两个对象不相等<br>
     * 通过 "=="和"equals"一起 判断<br>
     *
     * @param object1 对象1
     * @param object2 对象2
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月16日]
     * @author rain
     */
    public static void notEquals(Object object1, Object object2, String message, Object... parameters) {
        if (Objects.equals(object1, object2)) {
            fail(message);
        }
    }
    
    /**
     * 
     * 断言 字符串 cs 不匹配正则表达式: regexp
     *
     * @param cs 被断言的字符串
     * @param regexp 正则表达式
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月11日]
     * @author rain
     */
    public static void notMatcher(CharSequence cs, RegExp regexp, String message, Object... parameters) {
        AssertUtils.isFalse(PatternUtils.matcher(regexp, cs.toString()), message, parameters);
    }
    
    /**
     * 
     * 断言 字符串 cs 不匹配正则表达式: regexp
     *
     * @param cs 被断言的字符串
     * @param regexp 正则表达式
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年9月11日]
     * @author rain
     */
    public static void notMatcher(CharSequence cs, String regexp, String message, Object... parameters) {
        AssertUtils.isFalse(PatternUtils.matcher(regexp, cs.toString()), message, parameters);
    }
    
    /**
     * 
     * 断言对象为 null<br>
     * 提示信息样例: "{} is null!"."{}"就是参数,可以无限个
     *
     * @param object 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2015年12月15日]
     * @author rain
     */
    public static void notNull(Object object, String message, Object... parameters) {
        if (object == null) {
            fail(message, parameters);
        }
    }
    
    /**
     * 
     * 断言对象数组不为 null, 且数组中所有对象都不为 null<br>
     * 对象数据长度为0时,断言失败
     *
     * @param objects 断言对象
     * @param message 断言失败,提示信息
     * @param parameters 断言失败,提示信息参数
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年2月22日]
     * @author rain
     */
    public static void notNullByAll(Object[] objects, String message, Object... parameters) {
        if (objects == null || objects.length == 0) {
            fail(message, parameters);
        }
        
        for (Object object : parameters) {
            notNull(object, message, parameters);
        }
    }
}
